package rgroupdao

import (
	"vpn-management-server/logger"
	"vpn-management-server/src/dao"
	"vpn-management-server/src/model/rgroupmodel"
	"vpn-management-server/src/model/rulemodel"
)

func HasRuleGroup(name string, ugid int) bool {
	var rgroup rgroupmodel.RGroup
	sqlStr := "SELECT * FROM rgroup where name = ? and ug_id = ?"
	err := dao.GMysqlDB.Conn.Get(&rgroup, sqlStr, name, ugid)
	if err == nil {
		return true
	}
	return false
}

func AddRGroup(rgroup *rgroupmodel.RGroup) (int64, error) {
	sqlStr := "INSERT INTO rgroup(name,signer,description,ug_id) value(?,?,?,?)"
	result, err := dao.GMysqlDB.Conn.Exec(sqlStr, rgroup.Name, rgroup.Signer, rgroup.Description, rgroup.UGroupID)
	if err != nil {
		logger.Logger.Error(err)
		return -1, err
	}
	return result.LastInsertId()
}

func GetRGroupsCount(ugid int) int {
	var count int
	sqlStr := "SELECT COUNT(*) FROM rgroup WHERE ug_id = ?"
	err := dao.GMysqlDB.Conn.Get(&count, sqlStr, ugid)
	if err != nil {
		logger.Logger.Error(err)
		return -1
	}
	return count
}

func GetRGroupIDsByUGroupID(ugid int) []int {
	var rgroupIDs []int
	sqlStr := "SELECT id from rgroup where ug_id = ? "
	if err := dao.GMysqlDB.Conn.Select(&rgroupIDs, sqlStr, ugid); err != nil {
		logger.Logger.Error(err)
		return nil
	}
	return rgroupIDs
}

func GetRGroupIDsByUserID(uid int) []int {
	var rgroupIDs []int
	sqlStr := "SELECT rg_id from user_rgroups where u_id = ? "
	if err := dao.GMysqlDB.Conn.Select(&rgroupIDs, sqlStr, uid); err != nil {
		logger.Logger.Error(err)
		return nil
	}
	return rgroupIDs
}

func GrantRGroupToUGroup(rgid int, ugid int, singer string) error {
	sqlStr := "INSERT INTO ugroup_rgroups(ug_id,rg_id,signer) value(?,?,?)"
	if _, err := dao.GMysqlDB.Conn.Exec(sqlStr, ugid, rgid, singer); err != nil {
		logger.Logger.Error(err)
		return err
	}
	return nil
}

func GetRGroupsByPage(pageSize, pageNo, ugid int) []*rgroupmodel.RGroup {
	start := pageSize * (pageNo - 1)
	var rgroups []*rgroupmodel.RGroup
	sqlStr := "SELECT * from rgroup where ug_id = ? LIMIT ?,? "
	if err := dao.GMysqlDB.Conn.Select(&rgroups, sqlStr, ugid, start, pageSize); err != nil {
		logger.Logger.Error(err)
		return nil
	}
	return rgroups
}

func GetUserRGroupsByPage(pageSize, pageNo, uid int) []*rgroupmodel.RGroup {
	start := pageSize * (pageNo - 1)
	var RGIDs []int
	sqlStr := "SELECT rg_id from user_rgroups where u_id = ? LIMIT ?,? "
	if err := dao.GMysqlDB.Conn.Select(&RGIDs, sqlStr, uid, start, pageSize); err != nil {
		logger.Logger.Error(err)
		return nil
	}
	logger.Logger.Debug("RGIDs:", RGIDs)
	var RGroups []*rgroupmodel.RGroup
	for _, rgid := range RGIDs {
		if RGroup := GetRGroupByID(rgid); RGroup != nil {
			RGroups = append(RGroups, RGroup)
		}
	}
	return RGroups
}

func GetUserRGroupCount(uid int) int {
	var count int
	sqlStr := "SELECT COUNT(*) FROM user_rgroups WHERE u_id = ?"
	err := dao.GMysqlDB.Conn.Get(&count, sqlStr, uid)
	if err != nil {
		logger.Logger.Error(err)
		return -1
	}
	return count
}

func GetRGroupByID(rgid int) *rgroupmodel.RGroup {
	var rgroup rgroupmodel.RGroup
	sqlStr := "SELECT * from rgroup where id = ?"
	if err := dao.GMysqlDB.Conn.Get(&rgroup, sqlStr, rgid); err != nil {
		logger.Logger.Error(err)
		return nil
	}
	return &rgroup
}

func DeleteUserRGroup(rgid int) error {
	sqlStr := "DELETE From user_rgroups where rg_id = ?"
	if _, err := dao.GMysqlDB.Conn.Exec(sqlStr, rgid); err != nil {
		logger.Logger.Error(err)
		return err
	}
	return nil
}

func DeleteUGroupRGroup(rgid int) error {
	sqlStr := "DELETE From ugroup_rgroups where rg_id = ?"
	if _, err := dao.GMysqlDB.Conn.Exec(sqlStr, rgid); err != nil {
		logger.Logger.Error(err)
		return err
	}
	return nil
}

func DepriveRGroupFromUGroup(rgid int, ugid int) error {
	sqlStr := "DELETE From ugroup_rgroups where rg_id = ? and ug_id = ?"
	if _, err := dao.GMysqlDB.Conn.Exec(sqlStr, rgid, ugid); err != nil {
		logger.Logger.Error(err)
		return err
	}
	return nil
}

func DepriveAllRGroupFromUGroup(ugid int) error {
	sqlStr := "DELETE From ugroup_rgroups where ug_id = ?"
	if _, err := dao.GMysqlDB.Conn.Exec(sqlStr, ugid); err != nil {
		logger.Logger.Error(err)
		return err
	}
	return nil
}

func GrantRGroupToUser(rgid, uid int, signer string) error {
	sqlStr := "INSERT INTO user_rgroups(u_id, rg_id, signer) value (?,?,?)"
	if _, err := dao.GMysqlDB.Conn.Exec(sqlStr, uid, rgid, signer); err != nil {
		logger.Logger.Error(err)
		return err
	}
	return nil
}

func HasUserRGroup(rgid, uid int) bool {
	var count int

	sqlStr := "SELECT count(*) FROM user_rgroups where rg_id = ? and u_id = ?"
	err := dao.GMysqlDB.Conn.Get(&count, sqlStr, rgid, uid)
	if err == nil {
		return count >= 1
	}
	return false
}

func DepriveRGroupFromUser(rgid, uid int) error {
	sqlStr := "DELETE FROM user_rgroups WHERE u_id = ? and rg_id = ?"
	if _, err := dao.GMysqlDB.Conn.Exec(sqlStr, uid, rgid); err != nil {
		logger.Logger.Error(err)
		return err
	}
	return nil
}

func DepriveAllRGroupFromUser(uid int) error {
	sqlStr := "DELETE FROM user_rgroups WHERE u_id = ? "
	if _, err := dao.GMysqlDB.Conn.Exec(sqlStr, uid); err != nil {
		logger.Logger.Error(err)
		return err
	}
	return nil
}

func DeleteRGroupRule(rgid int) error {
	sqlStr := "DELETE From rgroup_rules where rg_id = ?"
	if _, err := dao.GMysqlDB.Conn.Exec(sqlStr, rgid); err != nil {
		logger.Logger.Error(err)
		return err
	}
	return nil
}

func DeleteRGroup(rgid int) error {
	sqlStr := "DELETE From rgroup where id = ?"
	if _, err := dao.GMysqlDB.Conn.Exec(sqlStr, rgid); err != nil {
		logger.Logger.Error(err)
		return err
	}
	return nil
}

func GrantRuleToRGroup(IDs []int, rgid int, singer string) error {
	tx, _ := dao.GMysqlDB.Conn.Begin()
	for _, id := range IDs {
		sqlStr := "INSERT INTO rgroup_rules(rg_id,r_id,signer) value(?,?,?)"
		// -1 表示是系统管理员或者
		_, err := tx.Exec(sqlStr, rgid, id, singer)
		if err != nil {
			logger.Logger.Error(err)
			tx.Rollback()
			return err
		}
	}
	return tx.Commit()
}

func HasRuleInRGroup(rid int, rgid int) bool {
	var rule rulemodel.Rule
	sqlStr := "SELECT * FROM rgroup_rules where rg_id = ? and r_id = ?"
	err := dao.GMysqlDB.Conn.Get(&rule, sqlStr, rgid, rid)
	if err == nil {
		return true
	}
	return false
}

func DepriveRuleFromRGroup(IDs []int, rgid int) error {
	tx, _ := dao.GMysqlDB.Conn.Begin()
	for _, id := range IDs {
		sqlStr := "DELETE FROM rgroup_rules WHERE rg_id = ? and r_id = ?"
		_, err := tx.Exec(sqlStr, rgid, id)
		if err != nil {
			logger.Logger.Error(err)
			tx.Rollback()
			return err
		}
	}
	return tx.Commit()
}

func GetUGroupIDsByRGroupID(rgid int) []int {
	var ugroupIDs []int
	sqlStr := "SELECT ug_id from ugroup_rgroups where rg_id = ? "
	if err := dao.GMysqlDB.Conn.Select(&ugroupIDs, sqlStr, rgid); err != nil {
		logger.Logger.Error(err)
		return nil
	}
	return ugroupIDs
}
